package com.yaDuo.common.base

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.Application
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Process
import android.text.TextUtils
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
import com.yaDuo.common.ui.GlobalContext
import com.yaDuo.common.util.LogUtil
import com.yaDuo.common.util.XxxlinHandler

open class BaseApplication : Application(), ViewModelStoreOwner {

    override val viewModelStore: ViewModelStore = ViewModelStore()

    companion object {

        private const val TAG = "BaseApplication"

        private var mAppViewModelStore: ViewModelStore? = null
        private var mApplicationProvider: ViewModelProvider? = null

        private var mUiHandler = Handler(Looper.getMainLooper())
        protected var mBackHandler: XxxlinHandler? = null
        protected var mSlowHandler: XxxlinHandler? = null
        protected var mBackThread: HandlerThread? = null
        protected var mSlowThread: HandlerThread? = null

        protected var isMainProcess: Boolean? = null

        private var mBaseApplication: BaseApplication? = null

        @JvmStatic
        fun get(): BaseApplication {
            return mBaseApplication!!
        }

        /**
         * 判断是不是主进程
         */
        fun isMainProcess() {
            if (isMainProcess == null) {
                isMainProcess = get().packageName.equals(getCurrentProcessName())
            }
        }

        /**
         * 获取当前进程名
         */
        private fun getCurrentProcessName(): String? {
            // 通过Application的API获取当前进程名
            var currentProcessName = getCurrentProcessNameByApplication()
            if (!TextUtils.isEmpty(currentProcessName)) {
                return currentProcessName
            }
            // 通过反射ActivityThread获取当前进程名
            currentProcessName = getCurrentProcessNameByActivityThread()
            if (!TextUtils.isEmpty(currentProcessName)) {
                return currentProcessName
            }
            // 通过ActivityManager获取当前进程名
            currentProcessName = getCurrentProcessNameByActivityManager()
            return currentProcessName
        }

        /**
         * 通过Application新的API获取进程名，无需反射和IPC，效率最高
         */
        private fun getCurrentProcessNameByApplication(): String? {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                return getProcessName()
            }
            return null
        }

        /**
         * 通过反射ActivityThread获取进程名，避免了IPC
         */
        @SuppressLint("DiscouragedPrivateApi", "PrivateApi")
        private fun getCurrentProcessNameByActivityThread(): String? {
            var processName: String? = null
            runCatching {
                val declaredMethod = Class.forName(
                    "android.app.ActivityThread", false,
                    Application::class.java.classLoader
                )
                    .getDeclaredMethod("currentProcessName", *arrayOfNulls(0))
                declaredMethod.isAccessible = true
                val invoke = declaredMethod.invoke(null)
                if (invoke is String) {
                    processName = invoke
                }
            }.onFailure { LogUtil.d(TAG, "getCurrentProcessNameByActivityThread failure") }
            return processName
        }

        /**
         * 通过ActivityManager获取进程名
         */
        private fun getCurrentProcessNameByActivityManager(): String {
            val pid: Int = Process.myPid()
            var processName: String? = ""
            val manager: ActivityManager =
                GlobalContext.get().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            for (process in manager.runningAppProcesses) {
                if (process.pid == pid) {
                    processName = process.processName
                }
            }
            return processName!!
        }
    }


    override fun onCreate() {
        super.onCreate()
        mBaseApplication = this
        mAppViewModelStore = ViewModelStore()

        GlobalContext.set(this)

        // 提升进程优先级
        XxxlinHandler.updateMaxPriority()
        // 死锁监听
        XxxlinHandler.initLockWatch()

        // 后台进程
        mBackThread = HandlerThread("TicketUnionBackThread")
        mBackThread!!.start()
        mBackHandler =
            XxxlinHandler(mBackThread!!.looper)


        // 缓慢线程，用于不重要的数据查询
        mSlowThread = HandlerThread("TicketUnionSlowThread")
        mSlowThread!!.start()
        mSlowHandler =
            XxxlinHandler(mSlowThread!!.looper)
        mSlowHandler!!.post {
            XxxlinHandler.updateToPriorityPriority(Process.THREAD_PRIORITY_BACKGROUND)
        }
    }


    protected fun <T : ViewModel> getApplicationScopeViewModel(modelClass: Class<T>): T {
        if (mApplicationProvider == null) {
            val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(this)
            mApplicationProvider = ViewModelProvider(viewModelStore, factory)
        }
        return mApplicationProvider!![modelClass]
    }

    /**
     * 切换到UI线程
     */
    fun runOnUiGround(r: Runnable, delay: Long = 0) {
        if (delay == 0L) {
            mUiHandler.post(r)
        } else {
            mUiHandler.postDelayed(r, delay)
        }
    }

    fun removeUiGroundCallback(r: Runnable) {
        mUiHandler.removeCallbacks(r)
    }

    /**
     * 切换到Back线程
     */
    fun runOnBackGround(r: Runnable, delay: Long = 0) {
        if (delay == 0L) {
            mBackHandler?.post(r)
        } else {
            mBackHandler?.postDelayed(r, delay)
        }
    }

    fun removeBackGroundCallback(r: Runnable) {
        mBackHandler?.removeCallbacks(r)
    }

    /**
     * 切换到Slow线程
     */
    fun runOnSlowGround(r: Runnable, delay: Long = 0) {
        if (delay == 0L) {
            mSlowHandler?.post(r)
        } else {
            mSlowHandler?.postDelayed(r, delay)
        }
    }

    fun removeSlowGroundCallback(r: Runnable) {
        mSlowHandler?.removeCallbacks(r)
    }

}